﻿using Company.Core.Attributes;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Company.Core.Extensions
{
    /// <summary>
    /// 在加载程序集模块时自动执行注册和获取标记为 ExposedService 的类。
    /// </summary>
    public static class DenpendencyExtension
    {
        /// <summary>
        /// 自动注册程序集下所有的标记为 ExposedService 的类。
        /// </summary>
        /// <param name="containerRegistry"></param>
        /// <param name="assembly"></param>
        public static void RegisterAssembly(this IContainerRegistry containerRegistry, Assembly assembly)
        {
            var list = GetExposedServiceAttributeTypes(assembly);
            foreach (var exposedServiceType in list)
            {
                var attr = exposedServiceType.GetCustomAttribute<ExposedServiceAttribute>();
                if (attr != null)
                {
                    if (attr.Lifetime == Lifetime.Singleton)
                    {
                        // 注册单例
                        containerRegistry.RegisterSingleton(exposedServiceType);

                        // 以接口注册
                        foreach (var itype in attr.Interfaces)
                        {
                            containerRegistry.RegisterSingleton(itype, exposedServiceType);
                        }
                    }
                    else
                    {
                        // 注册瞬态
                        containerRegistry.Register(exposedServiceType);

                        // 以接口注册
                        foreach (var itype in attr.Interfaces)
                        {
                            containerRegistry.Register(itype, exposedServiceType);
                        }
                    }

                }
            }
        }

        /// <summary>
        /// 自动实例化程序集下所有的标记为 ExposedService 的类。
        /// </summary>
        /// <param name="containerProvider"></param>
        /// <param name="assembly"></param>
        public static void InitializeAssembly(this IContainerProvider containerProvider, Assembly assembly)
        {
            var list = GetExposedServiceAttributeTypes(assembly);
            foreach (var exposedServiceType in list)
            {
                var attr = exposedServiceType.GetCustomAttribute<ExposedServiceAttribute>();
                if (attr != null && attr.AutoInitialize && attr.Lifetime == Lifetime.Singleton)
                {
                    containerProvider.Resolve(exposedServiceType); // 创建实例
                }
            }
        }

        /// <summary>
        /// 获取程序集中标记 ExposedService 特性的类
        /// </summary>
        /// <param name="assembly"></param>
        /// <returns></returns>
        private static List<Type> GetExposedServiceAttributeTypes(Assembly assembly)
        {
            return assembly.GetTypes().Where(d => d != null
                        && d.IsClass
                        && !d.IsAbstract
                        && d.CustomAttributes.Any(a => a.AttributeType == typeof(ExposedServiceAttribute))
                        ).ToList();
        }
    }
}
